package edu.mcw.rgd.clinminer.web;

import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
import com.vaadin.ui.Window;

import javax.annotation.PostConstruct;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.beans.factory.annotation.Value;
import org.vaadin.browsercookies.BrowserCookies;

import com.vaadin.event.ShortcutAction.KeyCode;

import edu.mcw.rgd.clinminer.security.ClinminerSecurityException;
import edu.mcw.rgd.clinminer.security.Security;
import edu.mcw.rgd.clinminer.security.Security.Roles;

@Configurable
public class LoginWindow extends Window implements
		BrowserCookies.UpdateListener {
	private static final long serialVersionUID = 1L;
	private static final Logger log = Logger.getLogger(LoginWindow.class);

	private FormLayout mainLayout;

	@Value("${database.username}")
	private transient String dbSchema;

	@Autowired
	private transient Security security;

	@Autowired
	private transient ClinminerApplication application;

	private Notification nErrorMessage;
	private Notification nInfoMessage;

	private TextField fUsername;
	private PasswordField fPassword;

	private static final String COOKIE_USERNAME = "clinmynehr.hmgc.mcw.edu-username-v2";

	public LoginWindow() {
		super("LoginWindow");
		setSizeUndefined();
		nErrorMessage = new Notification("Access denied",
				Notification.TYPE_ERROR_MESSAGE);
		nErrorMessage.setPosition(Notification.POSITION_CENTERED_TOP);
		nErrorMessage.setDelayMsec(2000);

		nInfoMessage = new Notification("Logged in successfully",
				Notification.TYPE_HUMANIZED_MESSAGE);
		nInfoMessage.setPosition(Notification.POSITION_CENTERED_TOP);
		nInfoMessage.setDelayMsec(1000);

		setCaption("Windows login");
		setReadOnly(true);
		setModal(true);
		setResizable(false);

		// select window theme
		setTheme("clinminer");
	}

	@PostConstruct
	private void init() {
		application.getCookies().addListener(this);

		buildMainLayout();
	}

	private void saveUsernameInCookie(String username) {
		application.setCookie(COOKIE_USERNAME, username);
	}

	private void buildMainLayout() {
		// loginForm_1
		mainLayout = new FormLayout();
		mainLayout.setMargin(true);
		mainLayout.setSizeUndefined();
		fUsername = new TextField();
		fPassword = new PasswordField();
		final Button bLogin = new Button("Login");
		bLogin.setWidth(7, UNITS_EM);

		fUsername.setCaption("Username");
		fUsername.focus();
		fUsername.setWidth(10, UNITS_EM);
		fPassword.setCaption("Password");
		fPassword.setWidth(10, UNITS_EM);
		// Spacer
		mainLayout.addComponent(new Label("&nbsp;", Label.CONTENT_XHTML));
		mainLayout.addComponent(fUsername);
		mainLayout.addComponent(fPassword);
		// Spacer
		mainLayout.addComponent(new Label("&nbsp;", Label.CONTENT_XHTML));
		mainLayout.addComponent(bLogin);

		setUsernameFromCookie();

		// Enter submits the form
		bLogin.setClickShortcut(KeyCode.ENTER);

		bLogin.addListener(new Button.ClickListener() {
			private static final long serialVersionUID = 1L;

			@Override
			public void buttonClick(ClickEvent event) {
				String username = (String) fUsername.getValue();
				String password = (String) fPassword.getValue();

				try {
					security.authenticate(username, password);
					saveUsernameInCookie(username);
					showMainUI();
				} catch (ClinminerSecurityException e) {
					fPassword.setValue("");
					nErrorMessage.setCaption(e.getMessage());
					showNotification(nErrorMessage);
				}

			}
		});

		setContent(mainLayout);
	}

	public void showMainUI() {
		getApplication().getMainWindow().setContent(
				new ClinminerEntityManagerView());
		showInfo();
		close();
	}

	public void showInfo() {
		// schema info
		if (security.isUserinRole(Roles.ROLE_CLINMINER_ADMIN)) {
			Window.Notification notif = null;
			if (dbSchema.equals("dss")) {
				notif = new Window.Notification("test",
						Window.Notification.TYPE_TRAY_NOTIFICATION);
			} else if (dbSchema.equals("clinminerdev")) {
				notif = new Window.Notification("production",
						Window.Notification.TYPE_TRAY_NOTIFICATION);
			} else {
				throw new UnsupportedOperationException("UNEXPECTED DB SCHEMA");
			}

			notif.setPosition(Window.Notification.POSITION_BOTTOM_LEFT);
			getApplication().getMainWindow().showNotification(notif);
		}
		// succesful login
		getApplication().getMainWindow().showNotification(nInfoMessage);
	}

	@Override
	// IMPORTANT as cookies won't be read on first load
	public void cookiesUpdated(BrowserCookies browserCookies) {
		setUsernameFromCookie();
		// detach listener
		application.getCookies().removeListener(this);
	}

	public void setUsernameFromCookie() {
		String usernameCookie = application.getCookie(COOKIE_USERNAME);
		if (usernameCookie != null && fUsername.getValue().equals("")) {
			fUsername.setValue(usernameCookie);
			fPassword.focus();
		}
	}

}
